package com.chuantou.yuba.ui;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import android.app.AlertDialog;
import android.app.DatePickerDialog;
import android.app.DatePickerDialog.OnDateSetListener;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.content.DialogInterface.OnKeyListener;
import android.content.Intent;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.DatePicker;
import android.widget.TextView;
import android.widget.Toast;

import com.android.volley.Request.Method;
import com.android.volley.Response.ErrorListener;
import com.android.volley.Response.Listener;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.NetworkImageView;
import com.chuantou.yuba.R;
import com.chuantou.yuba.api.RequestManager;
import com.chuantou.yuba.api.UriHelper;
import com.chuantou.yuba.api.request.GsonRequest;
import com.chuantou.yuba.api.request.MultiPartRequest;
import com.chuantou.yuba.api.to.BaseTO;
import com.chuantou.yuba.api.to.CityListTO;
import com.chuantou.yuba.api.to.CityTO;
import com.chuantou.yuba.api.to.UpdateAvatarDataTO;
import com.chuantou.yuba.api.to.UserTO;
import com.chuantou.yuba.ui.widget.AvatarPickerPopup;
import com.chuantou.yuba.util.AccountManager;
import com.chuantou.yuba.util.BitmapBinder;
import com.chuantou.yuba.util.Constants;
import com.chuantou.yuba.util.DateUtil;
import com.chuantou.yuba.util.UiUtil;
import com.chuantou.yuba.util.ViewHolder;
import com.google.gson.Gson;

/**
 * 个人资料主界面
 * 
 * @author dl1001
 * 
 */
public class ProfileDetailActivity extends BaseActionBarActivity implements OnClickListener {
	private static final int REQUEST_CODE_EDIT_NICKNAME = 1515;
	private static final int REQUEST_CODE_EDIT_SIGN = 1516;
	private static final int REQUEST_CODE_EDIT_FISHING_AGE = 1517;
	private static final int REQUEST_CODE_EDIT_FISHING_PLACE = 1518;
	private NetworkImageView mAvatarView;
	private TextView mNicknameView;
	private TextView mUidView;
	private TextView mSignView;
	private TextView mSexView;
	private TextView mBirthdayView;
	private TextView mDistrictView;
	private TextView mFishAgeView;
	private TextView mFishPlaceView;
	private DatePickerDialog mBirthDialog;
	private AccountManager mAccountManager;
	private UserTO mUser;
	private List<CityTO> mCities;
	private ProgressDialog mProgressDialog;
	private AvatarPickerPopup mPopup;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.profile_detail);
		mAccountManager = AccountManager.getInstance(getApplicationContext());
		mUser = mAccountManager.getUserTO();
		if (mUser == null) {
			finish();
			return;
		}
		setupViews();
		setTitle(R.string.profile);
	}

	private void setupViews() {
		mProgressDialog = new ProgressDialog(this);
		mProgressDialog.setMessage(getString(R.string.uploading));
		mProgressDialog.setCancelable(false);
		mAvatarView = (NetworkImageView) findViewById(R.id.avatar);
		BitmapBinder.bindCircularNetImage(getApplicationContext(), mAvatarView, mUser.getAvatar(), R.drawable.default_image_small);
		mNicknameView = (TextView) findViewById(R.id.nickname);
		mNicknameView.setText(mUser.getUsername());
		mUidView = (TextView) findViewById(R.id.uid);
		mUidView.setText(String.valueOf(mUser.getUid()));
		mSignView = (TextView) findViewById(R.id.sign);
		mSignView.setText(mUser.getMood());
		mSexView = (TextView) findViewById(R.id.sex);
		int sex = mUser.getSex();
		if (sex == Constants.SEX_FEMALE) {
			mSexView.setText(R.string.female);
		} else {
			mSexView.setText(R.string.male);
		}
		mBirthdayView = (TextView) findViewById(R.id.birthday);
		mBirthdayView.setText(mUser.getBirthday());
		mDistrictView = (TextView) findViewById(R.id.district);
		mDistrictView.setText(mUser.getCityName());
		mFishAgeView = (TextView) findViewById(R.id.fishing_age);
		mFishAgeView.setText(getString(R.string.fishing_age_format, mUser.getFishAge()));
		mFishPlaceView = (TextView) findViewById(R.id.fishing_place);
		mFishPlaceView.setText(mUser.getFishingAddress());
		findViewById(R.id.info_layout).setOnClickListener(this);
		findViewById(R.id.nickname_layout).setOnClickListener(this);
		findViewById(R.id.sign_layout).setOnClickListener(this);
		findViewById(R.id.birthday_layout).setOnClickListener(this);
		findViewById(R.id.district_layout).setOnClickListener(this);
		findViewById(R.id.fishing_age_layout).setOnClickListener(this);
		findViewById(R.id.fishing_place_layout).setOnClickListener(this);
		requestCity();
	}

	@Override
	public void onClick(View v) {
		switch (v.getId()) {
		case R.id.info_layout:
			pickAvatar();
			break;
		case R.id.nickname_layout: {
			Intent intent = new Intent(this, EditNicknameActivity.class);
			startActivityForResult(intent, REQUEST_CODE_EDIT_NICKNAME);
		}
			break;
		case R.id.sign_layout: {
			Intent intent = new Intent(this, EditSignActivity.class);
			startActivityForResult(intent, REQUEST_CODE_EDIT_SIGN);
		}
			break;
		case R.id.birthday_layout:
			showBirthDayDialog(v);
			break;
		case R.id.district_layout:
			showProvinceDialog();
			break;
		case R.id.fishing_age_layout: {
			Intent intent = new Intent(this, EditFishingAgeActivity.class);
			startActivityForResult(intent, REQUEST_CODE_EDIT_FISHING_AGE);
		}
			break;
		case R.id.fishing_place_layout: {
			Intent intent = new Intent(this, EditFishingPlaceActivity.class);
			startActivityForResult(intent, REQUEST_CODE_EDIT_FISHING_PLACE);
		}
			break;
		default:
			break;
		}
	}

	private void pickAvatar() {
		if (UiUtil.isFastDoubleClick()) {
			return;
		}
		if (mPopup != null && mPopup.isShowing())
			return;
		mPopup = new AvatarPickerPopup(this, true);
		ViewGroup decor = (ViewGroup) getWindow().getDecorView();
		mPopup.showAtLocation(decor, Gravity.BOTTOM, 0, 0);
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		getMenuInflater().inflate(R.menu.menu_more, menu);
		return super.onCreateOptionsMenu(menu);
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		if (item.getItemId() == R.id.menu_more) {
			Intent intent = new Intent(this, SettingActivity.class);
			startActivity(intent);
		}
		return super.onOptionsItemSelected(item);
	}

	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		super.onActivityResult(requestCode, resultCode, data);
		if (resultCode != RESULT_OK)
			return;
		switch (requestCode) {
		case REQUEST_CODE_EDIT_NICKNAME:
			String nickname = data.getStringExtra(Constants.EXTRA_DATA);
			mNicknameView.setText(nickname);
			mUser.setUsername(nickname);
			AccountManager.saveUser(getApplicationContext(), mUser);
			break;
		case REQUEST_CODE_EDIT_FISHING_AGE:
			int age = data.getIntExtra(Constants.EXTRA_DATA, 0);
			mFishAgeView.setText(getString(R.string.fishing_age_format, age));
			mUser.setFishAge(age);
			AccountManager.saveUser(getApplicationContext(), mUser);
			break;

		case REQUEST_CODE_EDIT_FISHING_PLACE:
			String fishingPlace = data.getStringExtra(Constants.EXTRA_DATA);
			mFishPlaceView.setText(fishingPlace);
			mUser.setFishingAddress(fishingPlace);
			AccountManager.saveUser(getApplicationContext(), mUser);
			break;

		case REQUEST_CODE_EDIT_SIGN:
			String sign = data.getStringExtra(Constants.EXTRA_DATA);
			mSignView.setText(sign);
			mUser.setMood(sign);
			AccountManager.saveUser(getApplicationContext(), mUser);
			break;
		case Constants.REQUEST_CODE_PICK_PHOTO:
		case Constants.REQUEST_CODE_TAKE_PHOTO:
			String avatarPath = data.getStringExtra("CropperPhotoPath");
			mAvatarView.clear();
			mAvatarView.setImageResource(R.drawable.add_avatar);
			File avatarFile = new File(avatarPath);
			updateAvatar(avatarFile);
			break;
		default:
			break;
		}
	}

	private void requestCity() {
		String url = UriHelper.getCityUrl();
		GsonRequest<CityListTO> request = new GsonRequest<CityListTO>(Method.POST, url, new Listener<CityListTO>() {

			@Override
			public void onResponse(CityListTO response) {
				if (response == null) {
					response = parseLocalCity();
				}
				if (response != null) {
					mCities = response.getCities();
				}
			}
		}, new ErrorListener() {

			@Override
			public void onErrorResponse(VolleyError error) {
				CityListTO list = parseLocalCity();
				if (list != null) {
					mCities = list.getCities();
				}
			}
		}, null, CityListTO.class);
		RequestManager.startRequest(getApplicationContext(), request);
	}

	private CityListTO parseLocalCity() {
		try {
			InputStream in = getAssets().open("cities");
			BufferedReader reader = new BufferedReader(new InputStreamReader(in));
			String str = reader.readLine();
			Gson gson = new Gson();
			return gson.fromJson(str, CityListTO.class);
		} catch (IOException e) {
			e.printStackTrace();
			return null;
		}
	}

	private void showProvinceDialog() {
		if (UiUtil.isFastDoubleClick())
			return;
		AlertDialog.Builder builder = new AlertDialog.Builder(this);
		builder.setTitle(R.string.choose_district);
		builder.setAdapter(new BaseAdapter() {

			@Override
			public View getView(int position, View convertView, ViewGroup parent) {
				if (convertView == null) {
					convertView = View.inflate(getApplicationContext(), R.layout.city, null);
				}
				CityTO city = mCities.get(position);
				TextView cityView = ViewHolder.get(convertView, R.id.city);
				cityView.setText(city.getName());
				return convertView;
			}

			@Override
			public long getItemId(int position) {
				return position;
			}

			@Override
			public Object getItem(int position) {
				return mCities == null ? null : mCities.get(position);
			}

			@Override
			public int getCount() {
				return mCities == null ? 0 : mCities.size();
			}

		}, new DialogInterface.OnClickListener() {

			@Override
			public void onClick(DialogInterface dialog, int which) {
				CityTO cityTO = mCities.get(which);
				showCityDialog(cityTO);
			}
		});
		builder.create().show();
	}

	private void showCityDialog(final CityTO province) {
		final List<CityTO> cities = province.getCities();
		AlertDialog.Builder builder = new AlertDialog.Builder(this);
		builder.setTitle(province.getName());
		builder.setAdapter(new BaseAdapter() {

			@Override
			public View getView(int position, View convertView, ViewGroup parent) {
				if (convertView == null) {
					convertView = View.inflate(getApplicationContext(), R.layout.city, null);
				}
				CityTO city = cities.get(position);
				TextView cityView = ViewHolder.get(convertView, R.id.city);
				cityView.setText(city.getName());
				return convertView;
			}

			@Override
			public long getItemId(int position) {
				return position;
			}

			@Override
			public Object getItem(int position) {
				return cities == null ? null : cities.get(position);
			}

			@Override
			public int getCount() {
				return cities == null ? 0 : cities.size();
			}

		}, new DialogInterface.OnClickListener() {

			@Override
			public void onClick(DialogInterface dialog, int which) {
				CityTO cityTO = cities.get(which);
				updateCity(province.getName(), province.getId(), cityTO.getName(), cityTO.getId());
			}
		});
		builder.create().show();
	}

	private void updateCity(final String province, final String provinceId, final String city, final String cityId) {
		if (mUser.isExpired()) {
			Toast.makeText(this, R.string.message_token_expired, Toast.LENGTH_SHORT).show();
			LoginActivity.start(this, -1, LoginActivity.ACTION_RETURN);
		} else {
			GsonRequest<BaseTO> request = RequestManager.getUpdateDistrictRequest(new Listener<BaseTO>() {

				@Override
				public void onResponse(BaseTO response) {
					if (!hasDestroyed()) {
						mProgressDialog.dismiss();
						if (response == null) {
							Toast.makeText(getApplicationContext(), R.string.update_failed, Toast.LENGTH_SHORT).show();
						} else {
							if (response.isSuccess()) {
								Toast.makeText(getApplicationContext(), R.string.update_success, Toast.LENGTH_SHORT).show();
								mUser.setStateName(province);
								mDistrictView.setText(city);
								mUser.setStateId(provinceId);
								mUser.setCityId(cityId);
								mUser.setCityName(city);
								AccountManager.saveUser(getApplicationContext(), mUser);
							} else if (response.getStatus() == BaseTO.STATUS_TOKEN_ERROR || response.getStatus() == BaseTO.STATUS_TOKEN_EXPIRED) {
								Toast.makeText(getApplicationContext(), R.string.message_token_expired, Toast.LENGTH_SHORT).show();
								LoginActivity.start(ProfileDetailActivity.this, -1, LoginActivity.ACTION_RETURN);
							} else {
								String msg = response.getMsg();
								msg = TextUtils.isEmpty(msg) ? getString(R.string.update_failed) : msg;
								Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_SHORT).show();
							}
						}
					}
				}
			}, new ErrorListener() {

				@Override
				public void onErrorResponse(VolleyError error) {
					if (!hasDestroyed()) {
						mProgressDialog.dismiss();
						Toast.makeText(getApplicationContext(), R.string.request_error, Toast.LENGTH_SHORT).show();
					}
				}
			}, mUser, province, city);
			mProgressDialog.show();
			RequestManager.startRequest(getApplicationContext(), request);
		}
	}

	private OnDateSetListener mBirthdayChangeListener = new OnDateSetListener() {

		@Override
		public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) {
			Calendar calendar = Calendar.getInstance();
			calendar.set(Calendar.YEAR, year);
			calendar.set(Calendar.MONTH, monthOfYear);
			calendar.set(Calendar.DAY_OF_MONTH, dayOfMonth);
			String birthday = DateUtil.getDateString(calendar.getTimeInMillis(), DateUtil.PATTERN_YMD);
			updateBirthday(birthday);
		}
	};

	private void showBirthDayDialog(View view) {
		if (UiUtil.isFastDoubleClick())
			return;
		view.setClickable(false);
		if (mBirthDialog != null && mBirthDialog.isShowing()) {
			return;
		}
		Date date = DateUtil.getDateObj(mUser.getBirthday(), DateUtil.PATTERN_YMD);
		Calendar calendar = Calendar.getInstance();
		// 超过100年初始化到今天
		int year = 0;
		if ((System.currentTimeMillis() - date.getTime()) < 100L * 365 * 24 * 60 * 60 * 1000) {
			calendar.setTimeInMillis(date.getTime());
			year = calendar.get(Calendar.YEAR);
		} else {
			year = calendar.get(Calendar.YEAR) - 16;
		}
		int month = calendar.get(Calendar.MONTH);
		int day = calendar.get(Calendar.DAY_OF_MONTH);
		mBirthDialog = new DatePickerDialog(this, mBirthdayChangeListener, year, month, day);
		DatePicker datePicker = mBirthDialog.getDatePicker();
		// 年龄选择16-24岁
		Calendar minCalendar = Calendar.getInstance();
		minCalendar.set(Calendar.YEAR, minCalendar.get(Calendar.YEAR) - 100);
		minCalendar.set(Calendar.MONTH, 0);
		minCalendar.set(Calendar.DAY_OF_MONTH, 0);
		minCalendar.set(Calendar.MINUTE, 0);
		minCalendar.set(Calendar.SECOND, 0);
		minCalendar.set(Calendar.MILLISECOND, 0);
		long minDate = minCalendar.getTimeInMillis();
		datePicker.setMinDate(minDate);
		datePicker.setMaxDate(Calendar.getInstance().getTimeInMillis());
		mBirthDialog.setOnKeyListener(new OnKeyListener() {

			@Override
			public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
				if (KeyEvent.KEYCODE_BACK == keyCode) {
					dialog.cancel();
					return true;
				}
				return false;
			}
		});
		mBirthDialog.show();
		view.setClickable(true);
	}

	private void updateBirthday(final String birthday) {
		if (mUser.isExpired()) {
			Toast.makeText(this, R.string.message_token_expired, Toast.LENGTH_SHORT).show();
			LoginActivity.start(this, -1, LoginActivity.ACTION_RETURN);
		} else {
			GsonRequest<BaseTO> request = RequestManager.getUpdateBirthdayRequest(new Listener<BaseTO>() {

				@Override
				public void onResponse(BaseTO response) {
					if (!hasDestroyed()) {
						mProgressDialog.dismiss();
						if (response == null) {
							Toast.makeText(getApplicationContext(), R.string.update_failed, Toast.LENGTH_SHORT).show();
						} else {
							if (response.isSuccess()) {
								Toast.makeText(getApplicationContext(), R.string.update_success, Toast.LENGTH_SHORT).show();
								mUser.setBirthday(birthday);
								mBirthdayView.setText(birthday);
								AccountManager.saveUser(getApplicationContext(), mUser);
							} else if (response.getStatus() == BaseTO.STATUS_TOKEN_ERROR || response.getStatus() == BaseTO.STATUS_TOKEN_EXPIRED) {
								Toast.makeText(getApplicationContext(), R.string.message_token_expired, Toast.LENGTH_SHORT).show();
								LoginActivity.start(ProfileDetailActivity.this, -1, LoginActivity.ACTION_RETURN);
							} else {
								String msg = response.getMsg();
								msg = TextUtils.isEmpty(msg) ? getString(R.string.update_failed) : msg;
								Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_SHORT).show();
							}
						}
					}
				}
			}, new ErrorListener() {

				@Override
				public void onErrorResponse(VolleyError error) {
					if (!hasDestroyed()) {
						mProgressDialog.dismiss();
						Toast.makeText(getApplicationContext(), R.string.request_error, Toast.LENGTH_SHORT).show();
					}
				}
			}, mUser, birthday);
			mProgressDialog.show();
			RequestManager.startRequest(getApplicationContext(), request);
		}
	}

	private void updateAvatar(final File avatarFile) {
		if (mUser.isExpired()) {
			Toast.makeText(this, R.string.message_token_expired, Toast.LENGTH_SHORT).show();
			BitmapBinder.bindCircularNetImage(getApplicationContext(), mAvatarView, mUser.getAvatar(), R.drawable.default_image_small);
			LoginActivity.start(this, -1, LoginActivity.ACTION_RETURN);
		} else {
			MultiPartRequest<UpdateAvatarDataTO> request = RequestManager.getUpdateAvatarRequest(new Listener<UpdateAvatarDataTO>() {

				@Override
				public void onResponse(UpdateAvatarDataTO response) {
					if (!hasDestroyed()) {
						mProgressDialog.dismiss();
						if (response == null) {
							Toast.makeText(getApplicationContext(), R.string.update_failed, Toast.LENGTH_SHORT).show();
							BitmapBinder.bindCircularNetImage(getApplicationContext(), mAvatarView, mUser.getAvatar(), R.drawable.default_image_small);
						} else {
							if (response.isSuccess()) {
								String newAvatar = response.getAvatar();
								mUser.setAvatar(newAvatar);
								BitmapBinder.bindCircularNetImage(getApplicationContext(), mAvatarView, newAvatar, R.drawable.default_avatar_round_small);
								AccountManager.saveUser(getApplicationContext(), mUser);
							} else {
								BitmapBinder.bindCircularNetImage(getApplicationContext(), mAvatarView, mUser.getAvatar(), R.drawable.default_image_small);
								if (response.getStatus() == BaseTO.STATUS_TOKEN_ERROR || response.getStatus() == BaseTO.STATUS_TOKEN_EXPIRED) {
									Toast.makeText(getApplicationContext(), R.string.message_token_expired, Toast.LENGTH_SHORT).show();
									LoginActivity.start(ProfileDetailActivity.this, -1, LoginActivity.ACTION_RETURN);
								} else {
									String msg = response.getMsg();
									msg = TextUtils.isEmpty(msg) ? getString(R.string.update_failed) : msg;
									Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_SHORT).show();
								}
							}
						}
					}
				}
			}, new ErrorListener() {

				@Override
				public void onErrorResponse(VolleyError error) {
					if (!hasDestroyed()) {
						mProgressDialog.dismiss();
						Toast.makeText(getApplicationContext(), R.string.request_error, Toast.LENGTH_SHORT).show();
						BitmapBinder.bindCircularNetImage(getApplicationContext(), mAvatarView, mUser.getAvatar(), R.drawable.default_image_small);
					}
				}
			}, mUser, avatarFile);
			mProgressDialog.show();
			RequestManager.startUpload(getApplicationContext(), request);
		}
	}

}
